package com.house.keeper.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.house.keeper.base.Result;
import com.house.keeper.base.ResultCode;
import com.house.keeper.constant.ConstantConfig;
import com.house.keeper.entity.RoleUser;
import com.house.keeper.entity.User;
import com.house.keeper.entity.bean.UserBean;
import com.house.keeper.entity.vo.LoginVo;
import com.house.keeper.entity.vo.UpdatePwdVo;
import com.house.keeper.entity.vo.UserVo;
import com.house.keeper.mapper.RoleUserMapper;
import com.house.keeper.mapper.UserMapper;
import com.house.keeper.redis.RedisTemplateUtil;
import com.house.keeper.service.UserService;
import com.house.keeper.shiro.util.ShiroUtils;
import com.house.keeper.util.BeanUtils;
import com.house.keeper.util.MD5Util;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author zjj
 * @date 2022-05-04
 */
@Service
public class UserServiceImpl implements UserService {
    private static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleUserMapper roleUserMapper;
    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    /**
     * 登录校验
     *
     * @param loginVo 登录用户信息
     * @return
     */
    @Override
    public Result checkLogin(LoginVo loginVo) {
        String userName = loginVo.getUserName();
        String pwd = loginVo.getUserPwd();
        Subject currentUser = SecurityUtils.getSubject();
//        判断校验是否通过
        if(!currentUser.isAuthenticated()){
            UsernamePasswordToken token = new UsernamePasswordToken(userName,pwd);
            try{
//            记住用户信息
                if(loginVo.getRememberMe()!=null && loginVo.getRememberMe()==1){
                    token.setRememberMe(true);
                }
//            存入用户
                currentUser.login(token);
                if(ShiroUtils.getUser()!=null){
                    return Result.success(ShiroUtils.getUser());
                }else{
                    return Result.failure(ResultCode.USER_NO);
                }
            }catch (UnknownAccountException uae){
                logger.info("对用户["+userName+"]进行登录验证...验证未通过，未知账户");
                return Result.failure(ResultCode.USER_NO);
            }catch (IncorrectCredentialsException ice){
                logger.info("对用户["+userName+"]进行登录验证...验证未通过，错误凭证");
                return Result.failure(ResultCode.USER_LOGIN_ERROR);
            }catch (LockedAccountException lae){
                logger.info("对用户["+userName+"]进行登录验证...验证未通过，账户已锁定");
                return Result.failure(ResultCode.USER_HAS_LOCKED);
            }catch (ExcessiveAttemptsException eae){
                logger.info("对用户["+userName+"]进行登录验证...验证未通过，错误次数过多");
                return Result.failure(ResultCode.USER_TOO_MUCH);
            }catch (AuthenticationException ae){
                logger.info("对用户["+userName+"]进行登录验证...验证未通过，堆栈轨迹如下");
                ae.printStackTrace();
                return Result.failure(ResultCode.USER_LOGIN_ERROR);
            }
        }else{
            if(ShiroUtils.getUser()!=null){
                return Result.success(ShiroUtils.getUser());
            }else{
                return Result.failure(ResultCode.USER_NO);
            }
        }
    }

    /**
     * 用户分页查询
     *
     * @param userVo 查询条件
     * @return
     */
    @Override
    public Result selectUserPage(UserVo userVo) {
        PageHelper.startPage(userVo.getPage(),userVo.getLimit());
        List<UserBean> userList = userMapper.selectUser(userVo);//用户数据
        PageInfo<UserBean> pageInfo = new PageInfo<>(userList);
        return Result.success(pageInfo.getList(), pageInfo.getTotal());
    }

    /**
     * 更新用户状态
     *
     * @param id 主键
     * @return
     */
    @Override
    public Result updateStatus(int id) {
        User user=userMapper.selectById(id);
        if(user==null){
            return Result.failure(ResultCode.USER_NO);
        }
        User us = new User();
        BeanUtils.copyBeanProp(us,user);

        if(user.getUserStatus()== ConstantConfig.STATUS_YES){
            us.setUserStatus(ConstantConfig.STATUS_NO);
        }
        if(user.getUserStatus()== ConstantConfig.STATUS_NO){
            us.setUserStatus(ConstantConfig.STATUS_YES);
        }
        int row = userMapper.updateById(us);
        if(row<=0){
            return Result.failure(ResultCode.USER_UPDATE_ERROR);
        }
        return Result.success();
    }

    /**
     * 添加或修改
     *
     *  回滚：一般抛出的是RuntimeExcept异常
     *  在spring框架下，所有的异常都被org.springframework重写为RuntimeExcept
     * @param userBean 用户信息
     * @return
     */
    @Override
    @Transactional
    public Result update(UserBean userBean) {
        if(userBean.getId()!=null){
            User user = userMapper.selectById(userBean.getId());
            if (user==null){
                return Result.failure(ResultCode.USER_NOT_EXIST);
            }
//            密码是否被更改
            if(!user.getUserPwd().equals(userBean.getUserPwd())){
                String pwd = MD5Util.encode(userBean.getUserPwd());
                userBean.setUserPwd(pwd);
            }
            int row=userMapper.updateById(userBean);
            if(row<=0){
                return Result.failure(ResultCode.USER_NOT_EXIST);
            }
        }else{
//            根据用户名查询用户收存在，用户不存在方可进行新增操作
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("user_name",userBean.getUserName());
            User user=userMapper.selectOne(wrapper);
            if(user!=null){
                return Result.failure(ResultCode.USER_HAS_EXIST);
            }
//            密码加密
            String pwd = MD5Util.encode(userBean.getUserPwd());
            userBean.setUserPwd(pwd);
//            添加
            int row =userMapper.insert(userBean);
            if(row<=0){
                return Result.failure(ResultCode.USER_NOT_EXIST);
            }
            RoleUser ru = new RoleUser();
            ru.setRoleId(userBean.getRoleId());
            ru.setUserId(userBean.getId());//插入之后自动生成用户表的主键id

            int row2 = roleUserMapper.insert(ru);
            if(row2<=0){
                return Result.failure(ResultCode.USER_NOT_EXIST);
            }
        }
        return Result.success();
    }

    /**
     * 更新密码
     *
     * @param updatePwdVo
     * @return
     */
    @Override
    public Result updatePwd(UpdatePwdVo updatePwdVo) {
        User us= JSONArray.parseObject(redisTemplateUtil.get(ConstantConfig.USER_INFO).toString(),User.class);
        if(us == null){
            return Result.failure(ResultCode.USER_NOT_EXIST);
        }
        us.setUserPwd(MD5Util.encode(updatePwdVo.getNewPwd()));
        int row = userMapper.updateById(us);
        if(row<=0){
            return Result.failure(ResultCode.USER_UPDATE_ERROR);
        }
        return Result.success();
    }

}
